package org.streets.eis.ext.analysis.components;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.tree.DefaultTreeModel;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.wicket.Page;
import org.apache.wicket.Session;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.IAjaxCallDecorator;
import org.apache.wicket.ajax.calldecorator.AjaxCallDecorator;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.html.tree.BaseTree;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.util.MapModel;
import org.apache.wicket.util.resource.IStringResourceStream;
import org.apache.wicket.util.resource.PackageResourceStream;
import org.apache.wicket.velocity.markup.html.VelocityPanel;
import org.streets.commons.util.StringUtils;
import org.streets.database.Limits;
import org.streets.database.datadict.ColumnDefinition;
import org.streets.database.datadict.DataDict;
import org.streets.database.datadict.TableDefinition;
import org.streets.database.datadict.impl.TableDefinitionImpl;
import org.streets.eis.EisWebSession;
import org.streets.eis.component.ChangedNotifyType;
import org.streets.eis.component.codegroup.ListCodeGroup;
import org.streets.eis.component.datetime.DateField;
import org.streets.eis.component.datetime.DateTimeField;
import org.streets.eis.component.datetime.TimeField;
import org.streets.eis.component.messagebox.MessageBox;
import org.streets.eis.component.tree.Node;
import org.streets.eis.component.tree.TreePanel;
import org.streets.eis.entity.User;
import org.streets.eis.ext.analysis.Const;
import org.streets.eis.ext.analysis.QuerySet;
import org.streets.eis.ext.analysis.entities.DisplayField;
import org.streets.eis.ext.analysis.entities.Field;
import org.streets.eis.ext.analysis.entities.OrderField;
import org.streets.eis.ext.analysis.entities.QueryStruct;
import org.streets.eis.ext.analysis.entities.WhereField;
import org.streets.eis.ext.analysis.internal.buildlogic.QueryBuilderLogic;
import org.streets.eis.ext.analysis.pages.BuildQueryPage;
import org.streets.eis.ext.analysis.pages.ExecQueryPage;
import org.streets.eis.ext.analysis.pages.VelocityModel;
import org.streets.eis.ext.analysis.services.QueryService;
import org.streets.eis.util.Pager;


public class QueryBuildPanel extends Panel implements ProcessSelectedValue {
	private static final long serialVersionUID = 1L;
	@Inject
	protected QueryBuilderLogic builder;	
	@Inject
	protected QueryService queryService;
	@Inject
	protected DataDict dict;

	private TreePanel tree;
	private IStringResourceStream template = new PackageResourceStream(BuildQueryPage.class,"queryresults.vm");
	private IModel<Map<String,VelocityModel>> templateContext;
	private VelocityModel vm = new VelocityModel();

	private QueryStruct currentQuery;
	
	final ListView<WhereField> lvWhereFields;
	//private transient WhereField currentWhereField= new WhereField();
	private  int changingWhereFieldIndex;
	
	private List<TableDefinition> selectedTables = new ArrayList<TableDefinition>(); 	
	private Pager pager = new Pager(0);

	final ModalWindow window;
	private SelectPage selectPage = null; 
	private MessageBox messageBox;
	
	final WebMarkupContainer panelTab = new WebMarkupContainer("panelTab");
	final WebMarkupContainer panelWhereField = new WebMarkupContainer("panelWhereField");
	final WebMarkupContainer panelDisplayField = new WebMarkupContainer("panelDisplayField");
	final WebMarkupContainer panelOrderField = new WebMarkupContainer("panelOrderField");
    final WebMarkupContainer panelResult = new WebMarkupContainer("panelResult");
    
    private Form form ;
    WebMarkupContainer panelSelectedTables;// = new WebMarkupContainer("panelForSelectedTables");

    
    
	public QueryBuildPanel(String id,QueryStruct query) {
		super(id);
		currentQuery = query;
		selectedTables.clear();
		selectedTables.addAll(getSelectedTables());
		
			
		Map<String, VelocityModel> map = new HashMap<String, VelocityModel>();
		map.put("result",vm);
		templateContext =  new MapModel<String, VelocityModel>(map);
			
		form = new Form("form");
		add(form);
		
		form.add(messageBox = new MessageBox("MessageBoxInPanel"));
		form.add(panelTab);
		panelSelectedTables = createSelectedTablesPanel("panelForSelectedTables");
		form.add(panelSelectedTables);

		
		panelTab.add(panelWhereField);
		panelTab.add(panelDisplayField);
		panelTab.add(panelOrderField);
		panelTab.add(panelResult);

		panelWhereField.setOutputMarkupId(true);
		panelDisplayField.setOutputMarkupId(true);
		panelOrderField.setOutputMarkupId(true);
		panelResult.setOutputMarkupId(true);
		panelTab.setOutputMarkupId(true);
			
		panelDisplayField.setVisible(false);
		panelWhereField.setVisible(true);
		panelOrderField.setVisible(false);
		panelResult.setVisible(false);

		FeedbackPanel feedbackPanel = new FeedbackPanel("feedback");
		feedbackPanel.setOutputMarkupId(true);
		add(feedbackPanel);
		
		//树形表列表1
		tree = new TreePanel<TableNode>("tablesTree", getTablesTreeModel()){
			private static final long serialVersionUID = 1L;
			@Override
			public void onNodeLabelClicked(Node<TableNode> node, BaseTree tree, AjaxRequestTarget target){
				TableNode tmp = (TableNode)node.getUserObject();
				if ( ! (StringUtils.isEmpty(tmp.parentId))){
					try{
						//TODO:change to joinTable
						builder.appendTable(currentQuery, tmp.name,"",false);
						selectedTables.clear();
						selectedTables.addAll(getSelectedTables());
						if (target != null) {
							target.addComponent(getPage());
						}
					}
					catch(Exception ex){
						showInfo("此表不能和已经选择的表联合查询！");
					}
				}
			}
		};
		
		form.add(tree);
	    tree.getTree().getTreeState().expandAll();
	    tree.getTree().setRootLess(true);


			// 查询名称
			form.add(new TextField<String>("txtName", new PropertyModel<String>(currentQuery, "name")));
			// 查询描述
			form.add(new TextField<String>("txtDesc", new PropertyModel<String>(currentQuery, "memo")));

			// 保存查询按钮
			form.add(new AjaxSubmitLink("linkSaveQuery"){
				private static final long serialVersionUID = 1L;
				@Override
				protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
					StringBuffer sb = new StringBuffer();
					if (! builder.isValid(currentQuery, sb)){
						showInfo(sb.toString());
						return;
					}
					try{
						builder.save(currentQuery);
						showInfo("保存成功!");
					}catch(Exception e){
						showError("保存失败:" + e.getMessage());
						e.printStackTrace();
					}
				}
			});

			// 取消查询按钮
			form.add(new Link<String>("linkCancelQuery", new Model<String>("")) {
				private static final long serialVersionUID = 1L;
				@Override
				public void onClick() {
					if (currentQuery.getId().equalsIgnoreCase("-1")){
						setResponsePage(new ExecQueryPage(null));
					}else{
						setResponsePage(new ExecQueryPage(currentQuery));
					}
				}
			});

			// 执行查询按钮
			form.add(new AjaxSubmitLink("linkExecQuery") {
				private static final long serialVersionUID = 1L;

				@Override
				protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
					StringBuffer sb = new StringBuffer();
					if (! builder.isValid(currentQuery, sb)){
						showInfo(sb.toString());
						return;
					}
					
					try{
						pager.first();
						
						//builder.fill(vm,currentQuery,pager);
                		Limits limit = Limits.of(pager.getStartRow(), pager.getPageSize());
                		User user = ((EisWebSession)Session.get()).getUser();
                		QuerySet qs = queryService.query(user, currentQuery, limit);
                		vm.fill(qs);
						
						
					}catch(Exception e){
						showError("执行错误:"+e.getMessage());
						e.printStackTrace();
						return ;
					}
								
					templateContext.getObject().remove("result");//修改model里的数据
					templateContext.getObject().put("result",vm);

					if (target != null){			
						panelResult.setVisible(true);
						panelWhereField.setVisible(false);
						panelDisplayField.setVisible(false);
						panelOrderField.setVisible(false);
						target.addComponent(panelTab);
						
					}
				}
			});

			panelSelectedTables = createSelectedTablesPanel(panelSelectedTables.getId());
			panelSelectedTables.setOutputMarkupId(true);

			// ***************************************************************************
			// 不仅要传递进去一个List给tab,而且点击tab里面的链接按钮，还要刷新外部的数据(AJax)？？
			// ***************************************************************************
			panelTab.add(new TabLink("linkShowPanelWF", "panelWhereField"));
			panelTab.add(new TabLink("linkShowPanelDF", "panelDisplayField"));
			panelTab.add(new TabLink("linkShowPanelOF", "panelOrderField"));
			panelTab.add(new TabLink("linkShowPanelRS", "panelResult"));
			

			// **显示条件字段
			List<WhereField> wherefields = currentQuery.getWhereFields();
			lvWhereFields = new ListView<WhereField>("listWhereFields", wherefields) {
				private static final long serialVersionUID = 1L;
				@Override
				protected void populateItem(ListItem<WhereField> item) {
					final WhereField field = (WhereField) item.getModelObject();
					item.add(new Label("lblWFAlias", field.getAlias()));
					item.add(new Label("lblWFTableName", field.getTableName()));
					item.add(new Label("lblWFFieldName", field.getFieldName()));
					//选择逻辑比较符号
					DropDownChoice ddcOperSign = new DropDownChoice("opsign", new PropertyModel<String>(field, "operSign"), Const.OPSIGN, new DDCChoiceRenderer("OPSIGN"));
					item.add(ddcOperSign);
					AjaxFormComponentUpdatingBehavior behavior = new AjaxFormComponentUpdatingBehavior("onchange") {
						private static final long serialVersionUID = 1L;
						protected void onUpdate(AjaxRequestTarget target) {
						}
					};
					ddcOperSign.add(behavior);
					//直接输入数据控件 : 当字段类型为代码和外键时不显示
					item.add(createTextField(field));//根据数据类型不同创建不同的验证条件的input控件
					//选择代码数据控件 : 当字段类型为代码时显示
					item.add(createListCodeGroup(field));
					//选择代码数据控件 : 当字段类型为外键时显示
					item.add(createSelectFKLink(field));
					//item.add(createForeignComboBox(field));
					item.add(moveUpLink("moveUpWF", item));
					item.add(moveDownLink("moveDownWF", item));
					//删除控件
					item.add(new AjaxFallbackLink<WhereField>("linkDelWhereField", new Model<WhereField>(field)) {
						private static final long serialVersionUID = 1L;
						@Override
						public void onClick(AjaxRequestTarget target) {
							builder.removeWhereField(currentQuery,(WhereField) getModelObject());
							if (target != null) {
								target.addComponent(panelWhereField);
							}
						}
					});

				}
			};
			//lvWhereFields.setOutputMarkupId(true);
			//lvWhereFields.setReuseItems(true);
			panelWhereField.add(lvWhereFields);

			// **显示显示字段
			List<DisplayField> dispfields = currentQuery.getDisplayFields();
			ListView<DisplayField> lvDisplayFields = new ListView<DisplayField>("listDisplayFields", dispfields) {
				private static final long serialVersionUID = 1L;

				@Override
				protected void populateItem(ListItem<DisplayField> item) {
					DisplayField field = (DisplayField) item.getModelObject();
					item.add(new Label("lblDFTableName", field.getTableName()));
					item.add(new Label("lblDFFieldName", field.getFieldName()));
					item.add(moveUpLink("moveUpDF", item));
					item.add(moveDownLink("moveDownDF", item));
					//删除控件
					item.add(new AjaxFallbackLink<DisplayField>("linkDelDisplayField", item.getModel()) {
						private static final long serialVersionUID = 1L;
						@Override
						public void onClick(AjaxRequestTarget target) {
							builder.removeDisplayField(currentQuery,(DisplayField) getModelObject());
							if (target != null) {
								target.addComponent(panelDisplayField);
								target.addComponent(panelSelectedTables);
							}
						}
					});
					DropDownChoice ddcFuncSign = new DropDownChoice("ddl_funcsign", new PropertyModel<String>(field, "funcSign"), Const.FUNCSIGN, new DDCChoiceRenderer("FUNCSIGN"));
					item.add(ddcFuncSign);
					AjaxFormComponentUpdatingBehavior behavior = new AjaxFormComponentUpdatingBehavior("onchange") {
						private static final long serialVersionUID = 1L;
						protected void onUpdate(AjaxRequestTarget target) {
						}
					};
					ddcFuncSign.add(behavior);
					
				}
			};
			panelDisplayField.add(lvDisplayFields);

			// **显示排序字段
			List<OrderField> orderfields = currentQuery.getOrderFields();
			final ListView<OrderField> lvOrderFields = new ListView<OrderField>("listOrderFields", orderfields) {
				private static final long serialVersionUID = 1L;

				@Override
				protected void populateItem(ListItem<OrderField> item) {
					OrderField field = (OrderField) item.getModelObject();
					item.add(new Label("lblOFTableName", field.getTableName()));
					item.add(new Label("lblOFFieldName", field.getFieldName()));
					item.add(moveUpLink("moveUpOF", item));
					item.add(moveDownLink("moveDownOF", item));
					//排序类别
					DropDownChoice ddcOrderSign = new DropDownChoice("orderSign", new PropertyModel<String>(field, "orderType"), Const.ORDERSIGN, new DDCChoiceRenderer("ORDERSIGN"));
					item.add(ddcOrderSign);
					AjaxFormComponentUpdatingBehavior behavior = new AjaxFormComponentUpdatingBehavior("onchange") {
						private static final long serialVersionUID = 1L;
						protected void onUpdate(AjaxRequestTarget target) {
						}
					};
					ddcOrderSign.add(behavior);
					//删除控件
					item.add(new AjaxFallbackLink<OrderField>("linkDelOrderField", item.getModel()) {
						private static final long serialVersionUID = 1L;

						@Override
						public void onClick(AjaxRequestTarget target) {
							builder.removeOrderField(currentQuery,(OrderField) getModelObject());
							if (target != null) {
								target.addComponent(panelOrderField);
								target.addComponent(panelSelectedTables);
							}
						}
					});
				}
			};
			panelOrderField.add(lvOrderFields);
			
			// 添加模板
		    VelocityPanel vp = new VelocityPanel("templatePanel", templateContext){
					private static final long serialVersionUID = 1L;
					@Override
					protected IStringResourceStream getTemplateResource()
					{
						return template;
					}
				};
			panelResult.add(vp);
			
			// 添加分页
			panelResult.add(new Label("lblPageCount",new PropertyModel(pager,"msg")));
			panelResult.add(new PagerAjaxLink("linkPageFirst","first"));
			panelResult.add(new PagerAjaxLink("linkPagePrevious","previous"));
			panelResult.add(new PagerAjaxLink("linkPageNext","next"));
			panelResult.add(new PagerAjaxLink("linkPageEnd","last"));
			

			// **编辑条件间的关系
			final WebMarkupContainer panelEditCondition = new WebMarkupContainer("panelEditCondition");
			panelEditCondition.setOutputMarkupId(true);
			panelEditCondition.setVisible(false);
			form.add(panelEditCondition);
			TextArea textarea = new TextArea<String>("textarea", new PropertyModel<String>(currentQuery, "fieldExpr"));
			panelEditCondition.add(textarea);
			
			form.add(new Link("linkOpenEdit") {
				private static final long serialVersionUID = 1L;
				@Override
				public void onClick() {
					panelEditCondition.setVisible(true);
				}
			});

			AjaxFallbackLink<String> linkCloseEdit = new AjaxFallbackLink<String>("linkCloseEdit", new Model<String>("Close")) {
			private static final long serialVersionUID = 1L;
				@Override
				public void onClick(AjaxRequestTarget target) {
					panelEditCondition.setVisible(false);
					target.addComponent(panelEditCondition);
				}
			};
			panelEditCondition.add(linkCloseEdit);

			panelEditCondition.add(new AjaxEditorLink("linkLeft", "("));
			panelEditCondition.add(new AjaxEditorLink("linkRight", ")"));
			panelEditCondition.add(new AjaxEditorLink("linkAnd", "AND"));
			panelEditCondition.add(new AjaxEditorLink("linkOr", "OR"));
			panelEditCondition.add(new AjaxEditorLink("linkEnter", "#"));
			
			panelEditCondition.add(new AjaxFallbackLink<String>("linkClear", new Model<String>("clear")) {
			private static final long serialVersionUID = 1L;
				@Override
				public void onClick(AjaxRequestTarget target) {
					currentQuery.setConditionExpr("");
					target.addComponent(panelEditCondition);
				}
			});

			
			panelEditCondition.add(new AjaxFallbackLink<String>("linkRebuild", new Model<String>("rebuild")) {
				private static final long serialVersionUID = 1L;
					@Override
					public void onClick(AjaxRequestTarget target) {
						String fieldExpr = builder.buildFieldExpr(currentQuery.getWhereFields(),"and");
						currentQuery.setConditionExpr(fieldExpr);
						target.addComponent(panelEditCondition);
					}
				});
			
			
			//选择窗口
			add(window = new ModalWindow("modalwindow"));
			selectPage = new SelectPage(null, window);
			window.setTitle("选择记录窗口");
			window.setPageMapName("modal-1");
			window.setCookieName("modal-1");

			window.setPageCreator(new ModalWindow.PageCreator()
			{
				public Page createPage()
				{
					return selectPage;
				}
			});
			window.setWindowClosedCallback(new ModalWindow.WindowClosedCallback()
			{
			 
				private static final long serialVersionUID = 1L;

				public void onClose(AjaxRequestTarget target)
				{
					CheckItem selected = selectPage.getCheckedItem();
					if(selected != null){
						currentQuery.getWhereFields().get(changingWhereFieldIndex).setValue(selected.getId());
						target.addComponent(getPage());
					}
				}
			});
			window.setCloseButtonCallback(new ModalWindow.CloseButtonCallback()
			{
				public boolean onCloseButtonClicked(AjaxRequestTarget target)
				{
					return true;
				}
			});

		}
	
		@SuppressWarnings("unchecked")
		private AjaxFallbackLink createSelectFKLink(final WhereField wf){
			IModel<WhereField> model = Model.of(wf);
			AjaxFallbackLink<WhereField> link = new AjaxFallbackLink<WhereField>("linkSelectValue",model){
 
				private static final long serialVersionUID = 1L;
				@Override
				public boolean isVisible() {
					return wf.isForeignKey();
				}

				@Override
				public void onClick(AjaxRequestTarget target) {
					WhereField field = (WhereField) getModelObject();
					ListItem li = (ListItem)getParent();
					changingWhereFieldIndex = li.getIndex();
					//System.out.println("currentWhereFieldIndex:" + changingWhereFieldIndex);
					//currentWhereField = new WhereField();
					
					String tableCode = builder.findParentTableCode(field.getTableCode(),field.getFieldCode());
					if (StringUtils.isEmpty(tableCode)){
						showInfo("没有找到对应的数据表!");
					}else{
						selectPage.changeItems(tableCode);
						window.show(target);
					}
				}
			};
			
			return link;
		}

		
		private List<TableDefinition> getSelectedTables(){
			List<TableDefinition> tables = new ArrayList<TableDefinition>();
			if (! StringUtils.isEmpty(currentQuery.getTableExpr())){
				String[] selectedTables = currentQuery.getTableExpr().split(",");
				for (String t_n : selectedTables) {
					tables.add(dict.getTableDef(t_n));
				}
			}
			return tables;
		}
		
		
		private ListCodeGroup createListCodeGroup(final WhereField wf){
			org.streets.eis.component.model.ListItem item = org.streets.eis.component.model.ListItem.empty();
			if( ! (StringUtils.isEmpty(wf.getValue())) && ( ! (StringUtils.isEmpty(wf.getValue())))){
				item = new org.streets.eis.component.model.ListItem(wf.getValue(),wf.getDispValue());
			}
			IModel<org.streets.eis.component.model.ListItem> m = Model.of(item);
			ListCodeGroup selectValue = new ListCodeGroup("selectvalue",m,wf.getAttr()){
				private static final long serialVersionUID = 1L;
				@Override
				protected ChangedNotifyType getChangedNotifyType(){
					return ChangedNotifyType.AJAX;
				}
				@Override
				public void onAjaxItemChanged(ListCodeGroup codeGroup,org.streets.eis.component.model.ListItem newValue,AjaxRequestTarget target){
					org.streets.eis.component.model.ListItem item = getModelObject();
					item.setId(newValue.getId());
					item.setText(newValue.getText());
					wf.setValue(newValue.getId());
					wf.setDispValue(newValue.getText());
				}
				
				@Override
				protected void onItemChanged(ListCodeGroup codeGroup,org.streets.eis.component.model.ListItem newValue){
					org.streets.eis.component.model.ListItem item = getModelObject();
					item.setId(newValue.getId());
					item.setText(newValue.getText());
					wf.setValue(newValue.getId());
					wf.setDispValue(newValue.getText());
				}
				
				
				@Override
				public boolean isVisible() {
					return wf.isCodeField();
				}
			};
			

			return selectValue;
		}
		
		
		@SuppressWarnings("unchecked")
		private TextField createTextField(final WhereField wf){
			if (wf.getDataType().equalsIgnoreCase("integer")) {
				return new TextField("entervalue",new PropertyModel<String>(wf, "value"),Integer.class){
					private static final long serialVersionUID = 1L;
					@Override
					public boolean isVisible() {
						return (wf.isCodeField() != true);
					}
				};
			}
			else if (wf.getDataType().equalsIgnoreCase("double"))
			{
				return new TextField("entervalue",new PropertyModel<String>(wf, "value"),Double.class){
					private static final long serialVersionUID = 1L;
					@Override
					public boolean isVisible() {
						return (wf.isCodeField() != true);
					}
				};
			}
			else if (wf.getDataType().equalsIgnoreCase("date")){
				DateField dt = new DateField("entervalue", new PropertyModel<java.sql.Date>(wf, "value")){
				private static final long serialVersionUID = 1L;
					@Override
					public boolean isVisible() {
						return (wf.isCodeField() != true);
					}
				};
				return dt;
			}else if (wf.getDataType().equalsIgnoreCase("time")){
				TimeField time = new TimeField("entervalue", new PropertyModel<java.sql.Time>(wf, "value")){
					private static final long serialVersionUID = 1L;
					@Override
					public boolean isVisible() {
						return (wf.isCodeField() != true);
					}
				};
				return time;
			}
			else if (wf.getDataType().equalsIgnoreCase("datetime")){
				DateTimeField datetime = new DateTimeField("entervalue", new PropertyModel<java.sql.Timestamp>(wf, "value")){
					private static final long serialVersionUID = 1L;
					@Override
					public boolean isVisible() {
						return (wf.isCodeField() != true);
					}
				};
				return datetime;
			}
			else{
				TextField t = new TextField<String>("entervalue", new PropertyModel<String>(wf, "value")){
						private static final long serialVersionUID = 1L;
						@Override
						public boolean isVisible() {
							return (wf.isCodeField() != true);
						}
				};
				t.add(createOnChangeBehavior());
				t.setOutputMarkupId(true);
				return t;
			}
		};

		
		
		private class TabLink extends Link {

			private static final long serialVersionUID = 1L;
			private String panelName;

			public TabLink(String id, String panelName) {
				super(id);
				this.panelName = panelName;
			}

			@Override
			public void onClick() {
				if (panelName.equalsIgnoreCase("panelWhereField")) {
					panelWhereField.setVisible(true);
					panelDisplayField.setVisible(false);
					panelOrderField.setVisible(false);
					panelResult.setVisible(false);
				}
				else if (panelName.equalsIgnoreCase("panelDisplayField")) {
					panelWhereField.setVisible(false);
					panelDisplayField.setVisible(true);
					panelOrderField.setVisible(false);
					panelResult.setVisible(false);
				}
				else if (panelName.equalsIgnoreCase("panelOrderField")) {
					panelWhereField.setVisible(false);
					panelDisplayField.setVisible(false);
					panelOrderField.setVisible(true);
					panelResult.setVisible(false);
				}
				else if (panelName.equalsIgnoreCase("panelResult")) {
					panelWhereField.setVisible(false);
					panelDisplayField.setVisible(false);
					panelOrderField.setVisible(false);
					panelResult.setVisible(true);
				}

			}

		}

		private class DDCChoiceRenderer extends ChoiceRenderer {
			private static final long serialVersionUID = 1L;
			private String renderType;

			public DDCChoiceRenderer(String renderType) {
				this.renderType = renderType;
			}

			@Override
			public String getDisplayValue(Object object) {
				if (renderType.equalsIgnoreCase("OPSIGN")) {
					return Const.OPSIGNNAMES.get(object);
				}
				else if (renderType.equalsIgnoreCase("ORDERSIGN")) {
					return Const.ORDERSIGNNAMES.get(object);
				}
				else if (renderType.equalsIgnoreCase("FUNCSIGN")) {
					return Const.FUNCSIGNNAMES.get(object);
				}

				return "";
			}
		};


		private class AjaxEditorLink extends AjaxLink {
			private static final long serialVersionUID = 1L;
			private String js = "";
			public AjaxEditorLink(String id, String editOp) {
				super(id);
				if (editOp == "AND") {
					js = "insertAtCursor(document.getElementById('demo1'),'AND');";
				}else if (editOp == "OR") {
					js = "insertAtCursor(document.getElementById('demo1'),'OR');";
				}
				else if (editOp == "(") {
					js = "insertAtCursor(document.getElementById('demo1'),'(');";
				}
				else if (editOp == ")") {
					js = "insertAtCursor(document.getElementById('demo1'),')');";
				}
				else if (editOp == "#") {// 换行
					js = "insertAtCursor(document.getElementById('demo1'),'\\n');";
				}

			}

			@Override
			public void onClick(AjaxRequestTarget target) {

			}

			protected IAjaxCallDecorator getAjaxCallDecorator() {
				return new AjaxCallDecorator() {
					private static final long serialVersionUID = 1L;

					public CharSequence decorateScript(CharSequence script) {
						return js + script;
					}
				};
			}

		};
		
		private OnChangeAjaxBehavior createOnChangeBehavior() {
			return new OnChangeAjaxBehavior() {
				private static final long serialVersionUID = 1L;
				@Override
				protected void onUpdate(AjaxRequestTarget target) {
					// target.addComponent(lblAgeValidate);
				}
			};
		}

		
		public IModel<List<org.streets.eis.component.model.ListItem>> getItems(String tableName){
			return new LoadableDetachableModel<List<org.streets.eis.component.model.ListItem>>(){
				private static final long serialVersionUID = 1L;
	    		public List<org.streets.eis.component.model.ListItem> load() {
	    			List<org.streets.eis.component.model.ListItem> list = new ArrayList<org.streets.eis.component.model.ListItem>();
	    			for(int i=0;i<20;i++){
	    				org.streets.eis.component.model.ListItem item =new org.streets.eis.component.model.ListItem(String.valueOf(i),"name"+i);
	    				list.add(item);
	    			}
					return list;
	    		}
			};
		}
		
		
		//所有表
	    private Node<TableNode> findParentNode(Node<TableNode> rootNode,String childNodeName){
	    	for(int i=0; i < rootNode.getChildCount(); i++){
	    		Node<TableNode> node = (Node<TableNode>)rootNode.getChildAt(i);//危险代码?
	    		if (((TableNode)node.getUserObject()).name.equalsIgnoreCase(childNodeName)){
	    			return node;
	    		}
	    	}
	    	
	    	return null;
	    }
	    
	    private DefaultTreeModel getTablesTreeModel(){	    	
	    	TableNode root = new TableNode();
	    	root.name="所有表";
	    	root.alias="所有表";
	    	root.parentId = "";
	    	final Node<TableNode> rootNode = new Node<TableNode>(root);
	    	rootNode.setLoaded(true);
	    	
	    	List<TableDefinition> list = dict.getTableDefs();
	    	for(TableDefinition table : list){
	    		if  ( ! (StringUtils.isEmpty(table.getCategory()))){
	    			Node<TableNode> parentNode = findParentNode(rootNode,table.getCategory());
	    			
	    			if (parentNode != null){
	    				parentNode.setLoaded(true);
	    				TableNode subNode = new TableNode();
	    				subNode.name = table.getName();
	    				subNode.alias = table.getAlias();
	    				subNode.parentId = table.getCategory();
	    				Node<TableNode> childNode = new Node<TableNode>(subNode);
	    				parentNode.add(childNode);
	    				childNode.setLoaded(true);
	    			}else{
	    				TableNode pNode = new TableNode();
	    				pNode.name = table.getCategory();
	    				pNode.alias = table.getCategory();
	    				pNode.parentId = "";
	    				Node<TableNode> newParentNode = new Node<TableNode>(pNode);

	    				TableNode subNode = new TableNode();
	    				subNode.name = table.getName();
	    				subNode.alias = table.getAlias();
	    				subNode.parentId = table.getCategory();
	    				Node<TableNode> childNode = new Node<TableNode>(subNode);
	    				
	    				newParentNode.add(childNode);
	    				rootNode.add(newParentNode);
	    				childNode.setLoaded(true);
	    				newParentNode.setLoaded(true);
	    			}
	    		}
	    	}
	    	
	    	DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
	    	return treeModel;
	    }
	    
	    
	    public List<ColumnWrapper> loadWrapperedFields(TableDefinition table){
			List<ColumnWrapper> list = new ArrayList<ColumnWrapper>();
			
			for(ColumnDefinition def : table.getColumns()){
				ColumnWrapper w = new ColumnWrapper(def);
				setDisplayProperty(w);
				setIfclauseProperty(w);
				setOrderProperty(w);	
				
				list.add(w);
			}
			
			return list;
		}

		
		private void setDisplayProperty(ColumnWrapper w){
			if (currentQuery != null){
				for(DisplayField f:currentQuery.getDisplayFields()){
					if (isSameField(f,w)){
						w.setDisplay(true);
						break;
					}
				}
			}
			}
			
			private void setIfclauseProperty(ColumnWrapper w){
			if (currentQuery != null){
				for(WhereField f:currentQuery.getWhereFields()){
					if (isSameField(f,w)){
						w.setIfclause(true);
						break;
					}
				}
			}
			}

			private void setOrderProperty(ColumnWrapper w){
				if (currentQuery != null){
					for(OrderField f:currentQuery.getOrderFields()){
					if (isSameField(f,w)){
						w.setOrder(true);
						break;
					}				
				}
			}
			}
			
			
			
			private boolean isSameField(Field f,ColumnWrapper w){
				if ((isSameTableName(f,w)) && (isSameFieldName(f,w))){
					return true;
				}else {
					return false;
				}
			}
						
			private boolean isSameTableName(Field f,ColumnWrapper w){
				return f.getTableCode().equalsIgnoreCase(w.getTable().getName());
			}
			private boolean isSameFieldName(Field f,ColumnWrapper w){
				return f.getFieldCode().equalsIgnoreCase(w.getName());
			}
			

			private void showError(String error){
				messageBox.error(error);
			}
			
			private void showInfo(String info){
				messageBox.alert(info);				
			}
			
			
			private WebMarkupContainer createSelectedTablesPanel(String id){
				WebMarkupContainer panel= new WebMarkupContainer(id); 
				panel.setOutputMarkupId(true);
				// **显示选择的表及其字段
				 ListView<TableDefinition> lvSelectedTables = new ListView<TableDefinition>("listSelectedTables", selectedTables) {
					private static final long serialVersionUID = 1L;
					
					@Override
					protected void populateItem(ListItem<TableDefinition> tableItem) {
						final TableDefinition table = (TableDefinition) tableItem.getModelObject();
						tableItem.add(new Label("lblSelectedTableName", table.getAlias()));
						// 删除表按钮
						final AjaxFallbackLink<TableDefinition> linkDeleteSelectedTable = new AjaxFallbackLink<TableDefinition>("linkDeleteSelectedTable", new Model<TableDefinition>(table)) {
						private static final long serialVersionUID = 1L;
						@Override
						public void onClick(AjaxRequestTarget target) {
							builder.removeTable(currentQuery, ((TableDefinitionImpl) getModelObject()).getName());
							if (target != null) {
								//target.addComponent(panel);//刷自己
								target.addComponent(panelWhereField);
								target.addComponent(panelDisplayField);
								target.addComponent(panelOrderField);
							}
						}
					};
						tableItem.add(linkDeleteSelectedTable);

						// 嵌套字段列表
						List<ColumnWrapper> fields = loadWrapperedFields(table);// 状态是如何保存的???
						tableItem.add(new ListView<ColumnWrapper>("listSelectedTableFields", fields) {
						private static final long serialVersionUID = 1L;
						@Override
						protected void populateItem(ListItem<ColumnWrapper> fieldItem) {
							final ColumnWrapper colwrapper = (ColumnWrapper) fieldItem.getModelObject();
							fieldItem.add(new Label("lblFieldName", colwrapper.getAlias()));
							
							//是否显示
							fieldItem.add(new AjaxCheckBox("chkDisplay", new PropertyModel<Boolean>(colwrapper, "display")) {
								private static final long serialVersionUID = 1L;
								
								@Override
								public void onUpdate(AjaxRequestTarget target) {
									builder.displayFieldSelectChanged(currentQuery,colwrapper);
									if (target != null) {
									  target.addComponent(panelDisplayField);
									}
								}
							});// chkDisplay

							// 条件可以多次添加，所以加个link
							fieldItem.add(new AjaxFallbackLink<ColumnWrapper>("linkAddWhereField", new Model<ColumnWrapper>(colwrapper)) {
								private static final long serialVersionUID = 1L;

								@Override
								public void onClick(AjaxRequestTarget target) {
									builder.appendWhereField(currentQuery,colwrapper);
									if (target != null) {
										target.addComponent(panelWhereField);
									}
								}
							});
							
							//是否排序
							fieldItem.add(new AjaxCheckBox("chkOrder", new PropertyModel<Boolean>(colwrapper, "order")) {
								private static final long serialVersionUID = 1L;

								@Override
								protected void onUpdate(AjaxRequestTarget target) {
									builder.orderFieldSelectionChanged(currentQuery,colwrapper);
									if (target != null){
										target.addComponent(panelOrderField);
									}
								}
							});// chkOrder

						}// 组装嵌套子项

					});// 嵌套字段列表

					}// 组装子项

				};// 表列表
			
				panel.add(lvSelectedTables);
			
				return panel;
			}


			public void processSelectedValue(CheckItem item) {
				//这种方式只在第一次刷新数据：奇怪???估计是恢复数据modal的顺序的问题
				//currentQuery.getWhereFields().add(currentQuery.getWhereFields().get(0));
				//currentQuery.getWhereFields().get(changingWhereFieldIndex).setValue(item.getId());
				//currentQuery.getWhereFields().clear();
			}


			private class PagerAjaxLink extends AjaxFallbackLink<Object>{
				
				private static final long serialVersionUID = 1L;
				private String op;
				public PagerAjaxLink(String id,String op) {
					super(id);
					this.op=op;
				}

				@Override
				public boolean isEnabled(){
					if (op.equalsIgnoreCase("first")){	
						return pager.getCurrentPage() != 1;
					}
					if (op.equalsIgnoreCase("previous")){	
						return pager.getCurrentPage() != 1;
					}
					if (op.equalsIgnoreCase("next")){	
						return (pager.getCurrentPage() != pager.getTotalPages()) &&(pager.getTotalPages() != 0 );
					}
					if (op.equalsIgnoreCase("last")){	
						return (pager.getCurrentPage() != pager.getTotalPages())&&(pager.getTotalPages() != 0 );
					}
					
					return true;
					
				}
				
				@Override
				public void onClick(AjaxRequestTarget target) {
					if (op.equalsIgnoreCase("first")){	
						pager.first();
					}
					if (op.equalsIgnoreCase("previous")){	
						pager.previous();
					}
					if (op.equalsIgnoreCase("next")){	
						pager.next();
					}
					if (op.equalsIgnoreCase("last")){	
						pager.last();
					}
					
					if (currentQuery != null) {
		    			//builder.fill(vm,currentQuery,pager);
                		Limits limit = Limits.of(pager.getStartRow(), pager.getPageSize());
                		User user = ((EisWebSession)Session.get()).getUser();
                		QuerySet qs = queryService.query(user, currentQuery, limit);
                		vm.fill(qs);
		    			
		    			
		    			templateContext.getObject().remove("result");//修改model里的数据
		    			templateContext.getObject().put("result",vm);
		        		target.addComponent(panelResult);
					}else{
						showInfo("请选择一个查询！");
					}
				}
							  
			  }
		
}
